package com.smf.lsc.authorization.security.service;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.smf.lsc.authorization.security.captcha.util.CodeProperties;
import com.smf.lsc.authorization.security.captcha.util.CodeUtil;


/**
 * 自定义登录请求过滤器
 * Created on 2021/11/19.
 *
 * @author ln
 * @since 1.0
 * 
 * 可以增加自定义信息，如验证码等
 * 
 */
public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
    public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
    public static final String SPRING_SECURITY_FORM_CODE_KEY = "code";
    private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
    private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
    private String codeParameter = SPRING_SECURITY_FORM_CODE_KEY;
    private boolean postOnly = true;

    @Autowired
	private CodeProperties codeProperties;
    
    @Autowired
    private CodeUtil codeUtil;
    
    public MyUsernamePasswordAuthenticationFilter(String defultFilterProcessesUrl) {
        super(new AntPathRequestMatcher(defultFilterProcessesUrl, "POST"));
    }
    
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {
        
    	if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
    	
    	//将原表单获取信息方式改为json获取方式
    	ObjectMapper mapper = new ObjectMapper();
    	Map<String,String> authenticationBean=new HashMap();
    	try 
    	{
	        InputStream is = request.getInputStream();
	        authenticationBean = mapper.readValue(is, Map.class);
	    } catch (IOException e) {
	    	e.printStackTrace();
	    	throw new AuthenticationServiceException("认证信息解析不正确! --"+e.getMessage() +"");
	    }
        String username = authenticationBean.get("userName");
        String password = authenticationBean.get("passWord");
        String code = authenticationBean.get("code");
        String codeRandom = authenticationBean.get("codeRandom");

        if (username == null) {
            username = "";
        }
        
        if (password == null) {
            password = "";
        }
        
        //自定义各种校验逻辑
        //验证码校验
        if(codeProperties.isEnable())
        {
	        if (code == null || "".equals(code)) {
	        	throw new AuthenticationServiceException("验证码不允许为空!");
	        }
	        else
	        {
	        	if(!codeUtil.checkVerifyCode(request, code,codeRandom))
	        	{
	        		throw new AuthenticationServiceException("验证码不正确!");
	        	}
	        }
        }
        
        //用户信息校验
        if((!username.equals("admin") && !username.equals("test")))
        {
        	throw new AuthenticationServiceException("登录信息不正确!");
        }
        
        username = username.trim();

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);

        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);

        return super.getAuthenticationManager().authenticate(authRequest);
    }

    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }
    
    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(passwordParameter).replaceAll(" ", "+");
    }

    protected String obtainUsername(HttpServletRequest request) {
        return request.getParameter(usernameParameter);
    }
    protected String obtainCode(HttpServletRequest request) {
        return request.getParameter(codeParameter);
    }

    protected void setDetails(HttpServletRequest request,
            UsernamePasswordAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }

    public void setUsernameParameter(String usernameParameter) {
//        Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
        this.usernameParameter = usernameParameter;
    }

    public void setPasswordParameter(String passwordParameter) {
//        Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
        this.passwordParameter = passwordParameter;
    }
    
    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    public final String getUsernameParameter() {
        return usernameParameter;
    }

    public final String getPasswordParameter() {
        return passwordParameter;
    }

}